"""
Generic functions
"""
#
# generic.py
#
# Copyright (C) 2012 Robert Buj Gelonch
# Copyright (C) 2012 David Megias Jimenez
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
__author__ = "Robert Buj Gelonch, and David Megias Jimenez"
__copyright__ = "Copyright 2012, Robert Buj Gelonch and David Megias Jimenez"
__credits__ = ["Robert Buj Gelonch", "David Megias Jimenez"]
__license__ = "GPL"
__version__ = "3"
__maintainer__ = "Robert Buj"
__email__ = "rbuj@uoc.edu"
__status__ = "Development"
__docformat__ = 'plaintext'

from itertools import cycle
from numpy import where, floor

def generic_detection_function(s, w, P_watermarking_sheme):
    """
    Return true whether almost all of the watermarked signal
    blocks, they are equal to the original watermarked block. It
    also returns the bit error rate and the block error rate.
    """
    # watermark message
    m = P_watermarking_sheme['message']
    fail = 0
    # loop variables
    w_cycle_iterator = cycle(w)
    num_frames = int(floor(len(s) / P_watermarking_sheme['frame_size']))
    BER = 0
    # loop: work within the splitted signal in blocks
    for frame in range(num_frames):
        start = frame * P_watermarking_sheme['frame_size']
        end = start + P_watermarking_sheme['frame_size']
        BER_frame = len(where(m[start:end] != w_cycle_iterator.next())[0])
        if BER_frame > (P_watermarking_sheme['frame_size'] / 2):
            fail = fail + 1
        BER = BER + BER_frame
    # last samples
    start = end
    if (num_frames * P_watermarking_sheme['frame_size']) != len(s):
        BER_frame = len(where(m[start:end] != w_cycle_iterator.next())[0])
        if BER_frame > (P_watermarking_sheme['frame_size'] / 2):
            fail = fail + 1
            num_frames = num_frames + 1
        BER = BER + BER_frame
    return ('BER:', BER, len(s), float(BER) / float(len(s))), ('FER:', fail, num_frames, float(fail) / float(num_frames)), fail == 0

def generic_detection_function_all(s, w, P_watermarking_sheme):
    """
    Return true whether all watermarked signal blocks, they are
    equal to the original watermarked block. It also returns the
    block error rate (FER)
    """
    # watermark message
    m = P_watermarking_sheme['message']
    fail = 0
    # loop variables
    w_cycle_iterator = cycle(w)
    num_frames = int(floor(len(s) / P_watermarking_sheme['frame_size']))
    # loop: work within the splitted signal in blocks
    for frame in range(num_frames):
        start = frame * P_watermarking_sheme['frame_size']
        end = start + P_watermarking_sheme['frame_size']
        if m[start:end].any() != w_cycle_iterator.next():
            fail = fail + 1
    # last samples
    start = end
    if (num_frames * P_watermarking_sheme['frame_size']) != len(s):
        if m[start:].any() != w_cycle_iterator.next():
            fail = fail + 1
            num_frames = num_frames + 1
    return ('FER:', fail, num_frames, float(fail) / float(num_frames)), fail == 0

def embedding_function(S, w=None, watermarking_sheme=None, ** P_watermarking_sheme):
    """
    Embedding Function Template.

    Embed a watermark message within an audio signal
    """
    return watermarking_sheme(S, w, P_watermarking_sheme)

def retrieval_function(s, watermarking_sheme=None, ** P_watermarking_sheme):
    """
    Retrieval Function Template.

    Return the embedded watermark message within the watermarked
    audio signal
    """
    return watermarking_sheme(s, P_watermarking_sheme)

def detection_function(s, w=None, watermarking_sheme=None, ** P_watermarking_sheme):
    """
    Detection Function Template.

    Evaluate whether the watermarked signal contains the water-
    marked message
    """
    return watermarking_sheme(s, w, P_watermarking_sheme)
